using System;
using System.Web;
using System.Web.Routing;
using ManagedUIFlow.Infrastructure.Commands;
using ManagedUIFlow.Infrastructure.Services;
using ManagedUIFlow.Model;
using Moq;
using Xunit;

namespace ManagedUIFlow.Specs.Infrastructure.Commands
{
    public class EndFlowSepcs
    {
        [Fact]
        public void EndFlow_RemovesFromSerializerStore()
        {
            var flow = new ManagedFlow("foo");
            var flowSeriailizerBuilder = new FlowViewServiceBuilder();
            var serializerMock = new Mock<IFlowViewService>();
            flowSeriailizerBuilder.SetFlowViewService(serializerMock.Object);
            var appControllerMock = new Mock<ApplicationController>();
            var requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            var endFlow = new EndFlow(requestContext)
                              {
                                  ApplicationController = appControllerMock.Object,
                                  FlowSerializerBuilder = flowSeriailizerBuilder
                              };
            
            endFlow.Execute(flow);

            serializerMock.Verify(s => s.Remove(flow, requestContext));
            appControllerMock.Verify(a => a.Execute(requestContext, It.IsAny<ManagedFlow>()), Times.Never());
        }

        [Fact]
        public void EndFlow_RestoresParentFlow()
        {
            var mainFlow = new ManagedFlow("bar");            
            var flow = new ManagedFlow(mainFlow.Key + "_" + Guid.NewGuid(), "foo", "", RedirectBehavior.Auto, "");
            var flowSeriailizerBuilder = new FlowViewServiceBuilder();
            var serializerMock = new Mock<IFlowViewService>();
            flowSeriailizerBuilder.SetFlowViewService(serializerMock.Object);            
            var appControllerMock = new Mock<ApplicationController>();
            var requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            serializerMock.Setup(s => s.Deserialize(mainFlow.Key.ToString(), requestContext)).Returns(mainFlow);
            var endFlow = new EndFlow(requestContext)
            {
                ApplicationController = appControllerMock.Object,
                FlowSerializerBuilder = flowSeriailizerBuilder
            };

            endFlow.Execute(flow);

            serializerMock.Verify(s => s.Remove(flow, requestContext));
            appControllerMock.Verify(a => a.Execute(requestContext, mainFlow));
        }

        [Fact]
        public void EndFlowResumingMainFlow_Throws()
        {
            var mainFlow = new ManagedFlow("bar");
            var flow = new ManagedFlow(mainFlow.Key + "_" + Guid.NewGuid(), "foo", "", RedirectBehavior.Auto, "");
            var flowSeriailizerBuilder = new FlowViewServiceBuilder();
            var serializerMock = new Mock<IFlowViewService>();
            flowSeriailizerBuilder.SetFlowViewService(serializerMock.Object);
            var appControllerMock = new Mock<ApplicationController>();
            var requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            var endFlow = new EndFlow(requestContext)
            {
                ApplicationController = appControllerMock.Object,
                FlowSerializerBuilder = flowSeriailizerBuilder
            };

            Assert.Throws<FlowException>(() => endFlow.Execute(flow));
        }
    }
}